﻿using System;

namespace Cpu6502.Opcodes
{
    public class ROR : Opcode
    {
        public ROR()
        {
            this.CpuCycles = 2;
            this.AddressType = CPU.AddressType.Implied;
        }

        public override void Execute()
        {
            Int16 data = (Int16)CPU.Registers.A;

            if (CPU.Registers.P.C)
                data |= 0x100;

            if ((data & 0x01) == 1)
                CPU.Registers.P.C = true;

            data >>= 1;

            // Set the Zero Flag if the data is 0
            CPU.Registers.P.Z = (data == 0);

            // If bit 7 of accumulator is set, then Negative flag must be set.
            CPU.Registers.P.N = (((data << 7) & 1) != 0);

            CPU.Registers.A = (byte)data;
        }
    }

    public class ROR_A : Opcode
    {
        public ROR_A()
        {
            this.CpuCycles = 6;
            this.AddressType = CPU.AddressType.Absolute;
        }

        public override void Execute()
        {
            Int16 data =
                 (Int16)CPU.Memory
                 [
                     MemoryHelper.GetAddress
                     (base.Argument, CPU.AddressType.Absolute)
                 ];

            if (CPU.Registers.P.C)
                data |= 0x100;

            if ((data & 0x01) == 1)
                CPU.Registers.P.C = true;

            data >>= 1;

            // Set the Zero Flag if the data is 0
            CPU.Registers.P.Z = (data == 0);

            // If bit 7 of accumulator is set, then Negative flag must be set.
            CPU.Registers.P.N = (((data << 7) & 1) != 0);

            CPU.Memory
            [
                MemoryHelper.GetAddress
                (base.Argument, CPU.AddressType.Absolute)
            ] = (byte)data;
        }
    }

    public class ROR_A_X : Opcode
    {
        public ROR_A_X()
        {
            this.CpuCycles = 7;
            this.AddressType = CPU.AddressType.AbsoluteIndexedX;
        }

        public override void Execute()
        {
            Int16 data =
                (Int16)CPU.Memory
                [
                    MemoryHelper.GetAddress
                    (base.Argument, CPU.AddressType.AbsoluteIndexedX)
                ];

            if (CPU.Registers.P.C)
                data |= 0x100;

            if ((data & 0x01) == 1)
                CPU.Registers.P.C = true;

            data >>= 1;

            // Set the Zero Flag if the data is 0
            CPU.Registers.P.Z = (data == 0);

            // If bit 7 of accumulator is set, then Negative flag must be set.
            CPU.Registers.P.N = (((data << 7) & 1) != 0);

            CPU.Memory
            [
                MemoryHelper.GetAddress
                (base.Argument, CPU.AddressType.AbsoluteIndexedX)
            ] = (byte)data;
        }
    }

    public class ROR_ZP : Opcode
    {
        public ROR_ZP()
        {
            this.CpuCycles = 5;
            this.AddressType = CPU.AddressType.ZeroPage;
        }

        public override void Execute()
        {
            Int16 data =
                (Int16)CPU.Memory
                [
                    MemoryHelper.GetAddress
                    (base.Argument, CPU.AddressType.ZeroPage)
                ];

            if (CPU.Registers.P.C)
                data |= 0x100;

            if ((data & 0x01) == 1)
                CPU.Registers.P.C = true;

            data >>= 1;

            // Set the Zero Flag if the data is 0
            CPU.Registers.P.Z = (data == 0);

            // If bit 7 of accumulator is set, then Negative flag must be set.
            CPU.Registers.P.N = (((data << 7) & 1) != 0);


            CPU.Memory
            [
                MemoryHelper.GetAddress
                (base.Argument, CPU.AddressType.ZeroPage)
            ] = (byte)data;
        }
    }

    public class ROR_ZP_X : Opcode
    {
        public ROR_ZP_X()
        {
            this.CpuCycles = 6;
            this.AddressType = CPU.AddressType.ZeroPageIndexedX;
        }

        public override void Execute()
        {
            Int16 data =
                (Int16)CPU.Memory
                [
                    MemoryHelper.GetAddress
                    (base.Argument, CPU.AddressType.ZeroPageIndexedX)
                ];

            if (CPU.Registers.P.C)
                data |= 0x100;

            if ((data & 0x01) == 1)
                CPU.Registers.P.C = true;

            data >>= 1;

            // Set the Zero Flag if the data is 0
            CPU.Registers.P.Z = (data == 0);

            // If bit 7 of accumulator is set, then Negative flag must be set.
            CPU.Registers.P.N = (((data << 7) & 1) != 0);


            CPU.Memory
            [
                MemoryHelper.GetAddress
                (base.Argument, CPU.AddressType.ZeroPageIndexedX)
            ] = (byte)data;
        }
    }
}